import tkinter as tk
from tkinter import messagebox
import math
import matplotlib.pyplot as plt
import numpy as np


# 基本数学运算
def calculate(expression):
    try:
        result = eval(expression)
        return str(result)
    except Exception as e:
        return "Error"


# 阶乘计算
def factorial(n):
    if n < 0:
        return "Error"
    return math.factorial(n)


# 求导
def derivative(f, x):
    try:
        # 简单的数值求导
        h = 1e-5
        return (eval(f.replace('x', str(x + h))) - eval(f.replace('x', str(x)))) / h
    except:
        return "Error"


# 画图功能
def plot():
    # 柱状图
    plt.bar(range(1, 6), np.random.rand(5))
    plt.title("Bar Chart")
    plt.show()

    # 饼状图
    plt.pie(np.random.rand(4), labels=['A', 'B', 'C', 'D'])
    plt.title("Pie Chart")
    plt.show()

    # 回归曲线
    x = np.linspace(0, 10, 100)
    y = 2 * x + np.random.normal(0, 1, 100)
    plt.scatter(x, y)
    plt.plot(x, 2 * x, color='red')
    plt.title("Regression Line")
    plt.show()


# 创意功能：随机数生成器
def random_number():
    return str(np.random.randint(1, 100))


# GUI部分
def on_keypress(key):
    expression = entry.get()
    if key == 'C':
        entry.delete(0, tk.END)
    elif key == '=':
        result = calculate(expression)
        entry.delete(0, tk.END)
        entry.insert(tk.END, result)
    else:
        entry.insert(tk.END, key)


def on_factorial():
    n = entry.get()
    result = factorial(int(n))
    entry.delete(0, tk.END)
    entry.insert(tk.END, result)


def on_derivative():
    f = entry.get()
    try:
        x = float(entry.get().split('x')[1])
        result = derivative(f, x)
        entry.delete(0, tk.END)
        entry.insert(tk.END, result)
    except:
        messagebox.showerror("Error", "Invalid input for derivative")


def on_random_number():
    result = random_number()
    entry.delete(0, tk.END)
    entry.insert(tk.END, result)


app = tk.Tk()
app.title("多功能计算器")

entry = tk.Entry(app, width=35, borderwidth=5)
entry.grid(row=0, column=0, columnspan=4, padx=10, pady=10)

button_text = [
    '7', '8', '9', '/', 'C',
    '4', '5', '6', '*', '√',
    '1', '2', '3', '-', '!',
    '0', '.', '=', '+', 'D',
    'f(x)', 'rand', 'plot', 'π'
]

row_val = 1
col_val = 0
for button in button_text:
    if button == 'C':
        b = tk.Button(app, text=button, command=lambda: on_keypress(button), height=2, width=6)
    elif button == '√':
        b = tk.Button(app, text=button, command=lambda: on_keypress('**0.5'), height=2, width=6)
    elif button == '!':
        b = tk.Button(app, text=button, command=on_factorial, height=2, width=6)
    elif button == 'D':
        b = tk.Button(app, text=button, command=on_derivative, height=2, width=6)
    elif button == 'rand':
        b = tk.Button(app, text=button, command=on_random_number, height=2, width=6)
    elif button == 'plot':
        b = tk.Button(app, text=button, command=plot, height=2, width=6)
    elif button == 'π':
        b = tk.Button(app, text=button, command=lambda: on_keypress('math.pi'), height=2, width=6)
    else:
        b = tk.Button(app, text=button, command=lambda: on_keypress(button), height=2, width=6)

    b.grid(row=row_val, column=col_val)
    col_val += 1
    if col_val > 3:
        col_val = 0
        row_val += 1

app.mainloop()